/**
 * 调用 Server.join 函数，能够保证你的 server 真正的起来(也就是说在 jetty start 之前 join 方法都是阻塞状态，避免 JVM 退出)
 * 
 * by @author lms start at 2022.05.21
 */
package ms.core.serv.system;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

import ms.core.serv.delegate.IAppDelegate;
import ms.core.serv.tool.ApiLoader;
import ms.core.serv.tool.TaskLoader;
import ms.core.serv.tool.WhiteIpLoader;
import ms.core.tool.Log4j2Tool;
import ms.core.tool.PropTool;
import ms.core.tool.StrTool;

public class Application {
	private static String SYSTEM_CONF	= "/config/server.properties";

	public static String UTF8			= "utf-8";

	public static String APP_NAME		= "helios.net";	// 微服务名称
	public static String APP_DELEGATE	= null;			// 应用程序委托类
	public static String APP_PATH		= "/";			// 应用部署路径
	public static boolean IP_FILTER 	= false;		// 启用IP过滤

	public static String CLIENT_ID		= "";			// 微服务编码(和平台上配置保持一致)
	public static String SECRET_KEY		= "";			// 微服务secretKey(和平台上配置保持一致)
	public static String SERVICE_URL	= "";			// 微服务地址
	public static int KEEP_ALIVE		= 10;			// 微服务与网关心跳间隔(单位秒)

	public static int MAX_CONN 			= 100;			// 微服务最大连接数
	public static String BIND_HOST  	= null;			// 绑定主机
	public static int BIND_PORT 		= 8000;			// 绑定端口
	public static String URL_ROOT 		= "/";			// 服务根目录
	public static String URL_SERVLET	= "/api";		// 服务api入口地址
	
	public static boolean GATEWAY_REGISTER 	= true;			// 服务是否在网关注册(true-将启动会话握手线程)
	public static String URL_GATEWAY 		= null;			// 网关地址
	public static String SERVLET_CORE 		= "sys.do";		// 网关框架servlet地址
	public static String SERVLET_WEB 		= "web.do";		// 网关应用servlet地址
	
	public static IAppDelegate appDelegate = null;
	private static Server serv = null;

	private static void initDelegate() {
		// 应用程序委托对象
		try {
			if (!StrTool.isBlank(APP_DELEGATE)) {
				Class<?> cls=Class.forName(APP_DELEGATE);
				appDelegate = cls.asSubclass(IAppDelegate.class).newInstance();
				appDelegate.beforeAppInited();
			}
		} catch(Exception e) {
			Log4j2Tool.error(Application.class, e);
		}
	}
	
	/**
	 * 加载配置参数
	 */
	private static void init() {
		PropTool tool = PropTool.getInstance(SYSTEM_CONF);
		APP_NAME	 = tool.getValue("appName", "helios.net");
		APP_DELEGATE = tool.getValue("appDelegate", null);
		APP_PATH	 = tool.getValue("appPath", "");
		IP_FILTER	 = "true".equalsIgnoreCase(tool.getValue("ipFilter", "true"));

		CLIENT_ID  	 = tool.getValue("clientId", "");
		SECRET_KEY 	 = tool.getValue("secretKey", "");
		SERVICE_URL	 = tool.getValue("serviceUrl", "");
		KEEP_ALIVE   = StrTool.strToInt(tool.getValue("keepAlive", "10"), 10);

		BIND_HOST	 = tool.getValue("bindHost", "127.0.0.1");
		BIND_PORT 	 = StrTool.strToInt(tool.getValue("bindPort", "8000"), 8000);
		URL_ROOT  	 = tool.getValue("root", "/");
		URL_SERVLET  = tool.getValue("servletUrl", "/api");
		MAX_CONN 	 = StrTool.strToInt(tool.getValue("maxConn", "100"), 100);

		GATEWAY_REGISTER = "true".equalsIgnoreCase(tool.getValue("gatewayRegister", "true"));
		URL_GATEWAY  	 = tool.getValue("gatewayUrl", "");
		SERVLET_CORE 	 = tool.getValue("gatewayCoreServlet", "sys.do");
		SERVLET_WEB  	 = tool.getValue("gatewayWebServlet", "web.do");
	}

	/**
	 * 提供接口供外部调用
	 */
	public static void run() {
		init();
		initDelegate();
		// 创建Server
		serv = new Server();
		// 配置连接最大数等
		ServerConnector connector = new ServerConnector(serv);
		connector.setAcceptQueueSize(MAX_CONN);
		connector.setHost(BIND_HOST);
		connector.setPort(BIND_PORT);
		serv.addConnector(connector);
		// 创建ServletContextHandler
		ServletContextHandler ctx = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
		ctx.setContextPath(URL_ROOT);
		// 创建servlet，地址:如=> http://localhost:8080/api
		ctx.addServlet(new ServletHolder(new CoreServlet()), URL_SERVLET);
		serv.setHandler(ctx);
		// 启动 server
		try {
			serv.start();
			// 1.加载应用配置并启动定时任务
			WhiteIpLoader.init();											// 加载IP白名单
			ApiLoader.init();												// 加载api配置表
			TaskLoader.start();												// 加载定时任务
			LWGAuthorization.start(CLIENT_ID, SECRET_KEY, SERVICE_URL);		// 启动服务注册
			String startType = GATEWAY_REGISTER ? "是":"否";
			Log4j2Tool.info(Application.class, APP_NAME+" 微服务已启动,网关注册<<"+startType+">>>,正在运行...");
			if (appDelegate!=null) appDelegate.afterAppInited();
			// 2.微服务进入运行
			serv.join();
		} catch (Exception e) {
			Log4j2Tool.error(Application.class, e);
		}
	}
	
	public static void stop() {
		try {
			Log4j2Tool.info(Application.class, APP_NAME+"微服务等待停止...");
			if (appDelegate!=null) appDelegate.beforeAppDestroy();
			serv.stop();
			TaskLoader.stop();												// 停止定时任务
			if (appDelegate!=null) appDelegate.afterAppDestroy();
			Log4j2Tool.info(Application.class, APP_NAME+"微服务已停止");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static String getSystemProperty(String key, String defaultValue) {
		PropTool tool = PropTool.getInstance(SYSTEM_CONF);
		return tool.getValue(key, defaultValue);
	}

	/**
	 * 提供通过shell方式调用
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		run();
	}
}
